<?php

namespace App\Http\Controllers\Mobile;


use App\Logics\MiniPayLogicV3;
use App\Models\SiteConfig;
use App\Service\Log\LogFile;

class PayController extends BaseController
{
    // 小程序支付 与 异步返回操作
    public function initialize()
    {
        parent::initialize();
    }

    ##################################################################################################################################
    // 活动报名：报名 + 支付 （前端不要调用的接口）
    public function _eventPay()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->eventAndPay($this->myUid);
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success([], '活动报名成功！');
    }

    // 认证：认证 + 支付（前端不要调用的接口）
    public function _authPay()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->authAndPay($this->myUid);
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success([], '活动报名成功！');
    }

    // 退款：退款 + 支付（前端不要调用的接口）
    public function _refundPay()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->refundAndPay($this->myUid);
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success([], '活动报名成功！');
    }

    ##################################################################################################################################

    // 活动报名：仅支付（已经下单的活动的支付）
    public function event()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->eventPay();
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success([], '活动报名成功！');
    }

    // 认证：仅支付
    public function auth()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->authPay($this->myUid);
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success($res, '认证支付信息返回成功！');
    }

    // 支付
    public function test()
    {
        $this->optLogic()->setField('to_mini', 1);

        $logic = new MiniPayLogicV3();
        $res   = $logic->test();
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success($res, '支付返回！');
    }

    // 退款测试
    public function testRefund()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->testRefund();
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success($res, '支付返回！');
    }

    // 提现测试
    public function testTransfer()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->testTransfer();
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success($res, '支付返回！');
    }

    // 获取商户序列号
    public function getSerialNo()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->getSerialNo();
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success($res, '从证书中获取的序列号与支付配置的一致！');
    }

    // 退款：仅支付（前端不要调用的接口）
    public function refund()
    {
        $logic = new MiniPayLogicV3();
        $res   = $logic->refundPay($this->myUid);
        if($res === false){
            return $this->error($logic->getError());
        }

        return $this->success($res, '获取退款成功！');
    }


    ##################################################################################################################################

    // 活动报名：回调
    public function eventNotify()
    {
        /* // 支付 返回前的验证操作
         $arrayInfo = $this->checkNotify();

         // 执行操作
         //  认证支付时间，支付状态，
         //  认证提成
         $this->logwx("info:".json_encode($arrayInfo));

         // 支付成功 后 的操作
         $trade_no = $arrayInfo['transaction_id'];
         $trade_no = $arrayInfo['out_trade_no'];*/

        $logic = new MiniPayLogicV3();
        $res   = $logic->eventNotify();
        if($res === false){
            $this->log($logic->getError());

            return $this->returnNotify(false);
        }

        return $this->returnNotify(true);
    }

    // 认证：回调
    public function authNotify()
    {
        /*// 支付 返回前的验证操作
        $arrayInfo = $this->checkNotify();

        // 执行操作
        //  认证支付时间，支付状态，
        //  认证提成
        $this->logwx("info:".json_encode($arrayInfo));

        // 支付成功 后 的操作
        $trade_no = $arrayInfo['transaction_id'];
        $trade_no = $arrayInfo['out_trade_no'];
        $res      = (new MiniPayLogicV3())->authNotify($trade_no);*/

        $logic = new MiniPayLogicV3();
        $res   = $logic->authNotify();
        if($res === false){
            $this->log($logic->getError());

            return $this->returnNotify(false);
        }

        return $this->returnNotify(true);
    }

    // 退款：回调
    public function refundNotify()
    {
        /*// 支付 返回前的验证操作
        $arrayInfo = $this->checkNotify();

        // 执行操作
        //  认证支付时间，支付状态，
        //  认证提成
        $this->logwx("info:".json_encode($arrayInfo));

        // 支付成功 后 的操作
        $trade_no = $arrayInfo['transaction_id'];
        $trade_no = $arrayInfo['out_trade_no'];
        $res      = (new MiniPayLogicV3())->refundNotify($trade_no);*/

        $logic = new MiniPayLogicV3();
        $res   = $logic->refundNotify();
        if($res === false){
            $this->log($logic->getError());

            return $this->returnNotify(false);
        }

        return $this->returnNotify(true);
    }

    // 提现：回调
    public function withdrawNotify()
    {
        /*// 支付 返回前的验证操作
        $arrayInfo = $this->checkNotify();

        // 执行操作
        //  认证支付时间，支付状态，
        //  认证提成
        $this->logwx("info:".json_encode($arrayInfo));

        // 支付成功 后 的操作
        $trade_no = $arrayInfo['transaction_id'];
        $trade_no = $arrayInfo['out_trade_no'];*/

        $logic = new MiniPayLogicV3();
        $res   = $logic->withdrawNotify();
        if($res === false){
            $this->log($logic->getError());

            return $this->returnNotify(false);
        }

        return $this->returnNotify(true);
    }


    // 回调接口

    /**
     * 微信支付V3
     * {
     * "mchid": "1378592502",
     * "appid": "wx945a8bf1b352f2b2",
     * "out_trade_no": "2023101812456352461771",
     * "transaction_id": "4200002041202310188575676363",
     * "trade_type": "JSAPI",
     * "trade_state": "SUCCESS",
     * "trade_state_desc": "支付成功",
     * "bank_type": "CMB_DEBIT",
     * "attach": "",
     * "success_time": "2023-10-18T15:01:01+08:00",
     * "payer": {
     * "openid": "ogOWZ5XyjE83swcHdG4hJtr-haDg"
     * },
     * "amount": {
     * "total": 1000,
     * "payer_total": 1000,
     * "currency": "CNY",
     * "payer_currency": "CNY"
     * }
     * }
     * @param Request $request
     * @return true|void
     */
    public function wxNotifyV3(Request $request, $mer_id)
    {
        $headers = $request->header();
        try{
            $config               = config('wechat')['payment']['default'];
            $inWechatpaySignature = $headers['wechatpay-signature'][0];
            $inWechatpayTimestamp = $headers['wechatpay-timestamp'][0];
            $inWechatpaySerial    = $config['serial'];
            $inWechatpayNonce     = $headers['wechatpay-nonce'][0];
            $inBody               = file_get_contents('php://input');
            $apiv3Key             = $config['key'];
            // 微信支付平台证书（下面有详细证书下载方法，一般在后台支付设置时调用）
            $platformPublicKeyInstance = Rsa::from('file://'.$config['serial_path'], Rsa::KEY_TYPE_PUBLIC);
            $verifiedStatus            = Rsa::verify(
                Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
                $inWechatpaySignature,
                $platformPublicKeyInstance
            );
            if($verifiedStatus){
                $inBodyArray = (array)json_decode($inBody, true);
                [
                    'resource' => [
                        'ciphertext'      => $ciphertext,
                        'nonce'           => $nonce,
                        'associated_data' => $aad,
                    ],
                ] = $inBodyArray;
                $inBodyResource      = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
                $inBodyResourceArray = (array)json_decode($inBodyResource, true);

                return $this->service->wxNotifyV3( // 下面有代码详解
                    $inBodyResourceArray['out_trade_no'],
                    $inBodyResourceArray['amount']['total'],
                    $inBodyResourceArray['transaction_id'],
                    $inBodyResourceArray['trade_type'],
                    $inBodyResourceArray['trade_state'],
                    $inBodyResourceArray['payer']['openid'],
                );
            }
        } catch(\Exception $e){
            return json_encode(['code' => 'FAIL', 'message' => '失败']);
        }
    }

    ##################################################################################################################################

    // 写入日志
    protected function log($log)
    {
        $logger = new LogFile();
        $logger->write($log, 'notify_return');
    }

    // 成功失败的返回
    protected function returnNotify($type = true)
    {
        if($type){
            $str = ['code' => 'SUCCESS', 'message' => '成功'];
        } else{
            $str = ['code' => 'FAIL', 'message' => '失败'];
        }

        $str = json_encode($str, JSON_UNESCAPED_UNICODE);
        $this->log($str);
        die($str);
    }

}


